package com.ervanalb.cellradio.shared.communicator.packets;

import java.nio.ByteBuffer;

/**
 * The payload of a packet. Contains a 1-byte type identifier followed by some
 * (or no) data, depending on the packet type. Includes routines to produce
 * specific packet type objects from a generic PacketData.
 * 
 * @author eric
 * @see Packet
 */
public class PacketData {
	public byte type;
	protected ByteBuffer data;

	public static final byte TYPE_ACK = 0;
	public static final byte TYPE_HELLO = 1;
	public static final byte TYPE_CONNECT = 2;
	public static final byte TYPE_CONNECTED = 3;
	public static final byte TYPE_AUTHENTICATE = 4;
	public static final byte TYPE_AUTHENTICATED = 5;
	public static final byte TYPE_HEARTBEAT = 6;
	public static final byte TYPE_ADVERTISE = 7;
	public static final byte TYPE_ERROR = 9;
	public static final byte TYPE_DISCONNECT = 10;

	public String toString() {
		return "Type " + type;
	}

	public PacketData(ByteBuffer bb) {
		type = bb.get();
		data = bb;
	}

	public PacketData(byte type, ByteBuffer bb) {
		this.type = type;
		this.data = bb;
	}

	public int size() {
		return 1 + data.remaining();
	}

	public ByteBuffer render() {
		ByteBuffer bb = ByteBuffer.allocate(size());
		bb.put(type);
		bb.put(data);
		bb.rewind();
		return bb;
	}

	public AckPacketData parseAck() {
		return new AckPacketData(data);
	}

	public HelloPacketData parseHello() {
		return new HelloPacketData(data);
	}

	public ConnectPacketData parseConnect() {
		return new ConnectPacketData(data);
	}

	public ConnectedPacketData parseConnected() {
		return new ConnectedPacketData(data);
	}

	public ErrorPacketData parseError() {
		return new ErrorPacketData(data);
	}

	public DisconnectPacketData parseDisconnect() {
		return new DisconnectPacketData(data);
	}

	public AuthenticatePacketData parseAuthenticate() {
		return new AuthenticatePacketData(data);
	}

	public AuthenticatedData parseAuthenticated() {
		return new AuthenticatedData(data);
	}

	public static String getString(ByteBuffer bb) {
		StringBuffer sb = new StringBuffer();
		int length = bb.getInt();
		for (int i = 0; i < length; i++)
			sb.append(bb.getChar());
		return sb.toString();
	}

	public static void putString(ByteBuffer bb, String string) {
		int length = string.length();
		bb.putInt(length);
		for (int i = 0; i < length; i++)
			bb.putChar(string.charAt(i));
	}

	public static int strlen(String s) {
		return s.length() * 2 + 4;
	}
}
